package com.csdn.eval.spring.mqtt.core;

import com.csdn.eval.spring.mqtt.model.MqttEventAnnotationDefinition;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * MQTT 事件工厂类，用于管理和查找 MQTT 事件定义
 */
public class MqttEventFactory {

    private final Map<String, MqttEventAnnotationDefinition> eventDefinitionMap = new ConcurrentHashMap<>();

    /**
     * 获取匹配指定topic的事件定义
     *
     * @param topic MQTT主题
     * @return 匹配的事件定义，未找到返回null
     */
    public MqttEventAnnotationDefinition getEventDefinition(String topic) {
        if (!StringUtils.hasText(topic)) {
            return null;
        }

        // 先检查精确匹配
        MqttEventAnnotationDefinition definition = eventDefinitionMap.get(topic);
        if (definition != null) {
            return definition;
        }

        return findWildcardMatch(topic).orElse(null);
    }

    /**
     * 注册事件定义
     *
     * @param eventDefinition 事件定义对象
     */
    public void registerEventDefinition(MqttEventAnnotationDefinition eventDefinition) {
        if (eventDefinition != null && StringUtils.hasText(eventDefinition.getTopic())) {
            eventDefinitionMap.put(eventDefinition.getTopic(), eventDefinition);
        }
    }

    /**
     * 根据topic获取对应的事件类
     *
     * @param topic MQTT主题
     * @return 事件类，未找到返回null
     */
    public Class<?> getClassTypeByTopic(String topic) {
        if (!StringUtils.hasText(topic)) {
            return null;
        }

        // 先检查精确匹配
        MqttEventAnnotationDefinition definition = eventDefinitionMap.get(topic);
        if (definition != null) {
            return definition.getEventClass();
        }

        // 通配符匹配
        return findWildcardMatch(topic)
                .map(MqttEventAnnotationDefinition::getEventClass)
                .orElse(null);
    }

    /**
     * 查找通配符匹配的事件定义
     *
     * @param topic 要匹配的topic
     * @return 匹配的事件定义Optional
     */
    private Optional<MqttEventAnnotationDefinition> findWildcardMatch(String topic) {
        return eventDefinitionMap.entrySet().stream()
                .filter(entry -> MqttTopic.isMatched(entry.getKey(), topic))
                .findFirst()
                .map(Map.Entry::getValue);
    }
}